package org.miyuki4j.cfgtool.generator;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import lombok.extern.slf4j.Slf4j;
import org.miyuki4j.cfgtool.*;
import org.miyuki4j.cfgtool.exception.CodeGenerateException;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Desc
 * @Author miyuki4j
 * @Date 2025/7/24/星期四 12:33
 * @Version 1.0
 */
@Slf4j
public class FreeMarkerCodeGenerator implements CodeGenerator {

    private Template __template__;
    private Template template;

    private boolean useLombok;

    @Override
    public void init() throws Exception {
        final String encoding = TableConfig.get(TableConfig.ConfigKeyEnum.ENCODING);
        final Version version = TableConfig.get(TableConfig.ConfigKeyEnum.FREEMARKER_VERSION);
        final String __templateName__ = TableConfig.get(TableConfig.ConfigKeyEnum.FREEMARKER_TEMPLATE_NAME);
        final String templateName = TableConfig.get(TableConfig.ConfigKeyEnum.FREEMARKER_FINAL_TEMPLATE_NAME);
        useLombok = TableConfig.get(TableConfig.ConfigKeyEnum.CODE_GENERATE_USE_LOMBOK);
        final Configuration cfg = new Configuration(version);
        final String templateDir = TableConfig.get(TableConfig.ConfigKeyEnum.FREEMARKER_TEMPLATE_DIR);
        if (TableConfig.has(TableConfig.ConfigKeyEnum.FREEMARKER_TEMPLATE_DIR)) {
            cfg.setDirectoryForTemplateLoading(new File(templateDir));
        } else {
            cfg.setClassLoaderForTemplateLoading(getClass().getClassLoader(), templateDir);
        }
        cfg.setDefaultEncoding(encoding);
        __template__ = cfg.getTemplate(__templateName__, encoding);
        template = cfg.getTemplate(templateName, encoding);
    }

    @Override
    public void generate(String outputDir, TableMeta meta) {
        try {
            final String packageName = meta.getPackageName();
            final String className = meta.getTableName();
            final String __className__ =  "__" + className + "__";
            final List<TableField> fields = meta.getHeader().getFields();

            // 0.自动文件夹
            final String packagePath = packageName.replace(".", "/");
            final File dir = new File(outputDir, packagePath);
            dir.mkdirs();

            // 1.父类部分
            final Map<String, Object> __dataModel__ = new HashMap<>();
            __dataModel__.put("packageName", packageName);
            __dataModel__.put("className", __className__);
            __dataModel__.put("fields", fields);
            __dataModel__.put("idType", meta.getIdType());
            __dataModel__.put("superClass", AbstractConf.class.getName());
            __dataModel__.put("useLomBok", useLombok);
            __dataModel__.put("fieldAnno", org.miyuki4j.cfgtool.TableFieldAnno.class.getName());
            __dataModel__.put("classAnno", org.miyuki4j.cfgtool.TableClassAnno.class.getName());
            final File __javaFile__ = new File(dir, __className__ + ".java");
            try (Writer writer = new FileWriter(__javaFile__)) {
                __template__.process(__dataModel__, writer);
                writer.flush();
                log.info("✅ Java 文件生成成功：{}", __javaFile__.getAbsolutePath());
            }

            // 2.子类部分
            final Map<String, Object> dataModel = new HashMap<>();
            dataModel.put("packageName", packageName);
            dataModel.put("className", className);
            dataModel.put("superClass", __className__);
            dataModel.put("classAnno", org.miyuki4j.cfgtool.TableClassAnno.class.getName());
            final File javaFile = new File(dir, className + ".java");
            if (!javaFile.exists()) {
                try (Writer writer = new FileWriter(javaFile)) {
                    template.process(dataModel, writer);
                    writer.flush();
                    log.info("✅ Java 文件生成成功：{}", javaFile.getAbsolutePath());
                }
            }
        } catch (Exception e) {
            throw new CodeGenerateException("生成Java文件失败, className=" + meta.getClassName(), e);
        }
    }

    @Override
    public void exit() {
        __template__ = null;
        log.info("✅ {} exit", getClass().getSimpleName());
    }
}
